﻿/************************************************************************

 This file is part of Chroma.

 EscapeFromPrisonPlanet is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 EscapeFromPrisonPlanet is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with Foobar.  If not, see <http://www.gnu.org/licenses/>.

************************************************************************/

// All code (c)2013 Scott Bevin. all rights reserved

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace LudumDare26.PrimitiveRendering
{
	public class PEEllipse : PEPrimitive
	{
		public float XRadius;
		public float YRadius;

		public override int PrimitiveCount { get { return primitiveCount; } }

		private static Vector3[] tempArray1 = new Vector3[slices];
		private static Vector3[] tempArray2 = new Vector3[slices];

		private int primitiveCount = 0;

		private const int slices = 32;

		#region Circle Identity Coordinates

		private static Vector3[] circleIdentityCoords = new Vector3[] {
            new Vector3(0.5000f, 0.0000f, 0f),
            new Vector3(0.4904f, 0.0975f, 0f),
            new Vector3(0.4619f, 0.1913f, 0f),
            new Vector3(0.4157f, 0.2778f, 0f),
            new Vector3(0.3536f, 0.3536f, 0f),
            new Vector3(0.2778f, 0.4157f, 0f),
            new Vector3(0.1913f, 0.4619f, 0f),
            new Vector3(0.0975f, 0.4904f, 0f),
            new Vector3(0.0000f, 0.5000f, 0f),
            new Vector3(-0.0975f, 0.4904f, 0f),
            new Vector3(-0.1913f, 0.4619f, 0f),
            new Vector3(-0.2778f, 0.4157f, 0f),
            new Vector3(-0.3536f, 0.3536f, 0f),
            new Vector3(-0.4157f, 0.2778f, 0f),
            new Vector3(-0.4619f, 0.1913f, 0f),
            new Vector3(-0.4904f, 0.0975f, 0f),
            new Vector3(-0.5000f, 0.0000f, 0f),
            new Vector3(-0.4904f, -0.0975f, 0f),
            new Vector3(-0.4619f, -0.1913f, 0f),
            new Vector3(-0.4157f, -0.2778f, 0f),
            new Vector3(-0.3536f, -0.3536f, 0f),
            new Vector3(-0.2778f, -0.4157f, 0f),
            new Vector3(-0.1913f, -0.4619f, 0f),
            new Vector3(-0.0975f, -0.4904f, 0f),
            new Vector3(0.0000f, -0.5000f, 0f),
            new Vector3(0.0975f, -0.4904f, 0f),
            new Vector3(0.1913f, -0.4619f, 0f),
            new Vector3(0.2778f, -0.4157f, 0f),
            new Vector3(0.3536f, -0.3536f, 0f),
            new Vector3(0.4157f, -0.2778f, 0f),
            new Vector3(0.4619f, -0.1913f, 0f),
            new Vector3(0.4904f, -0.0975f, 0f),
        };

		#endregion Circle Identity Coordinates

		public PEEllipse()
		{
			Type = PEPrimitiveType.Circle;
		}

		public PEEllipse(Vector2 center, float xradius, float yradius)
		{
			Type = PEPrimitiveType.Circle;
			Position = center;
			XRadius = xradius;
			YRadius = yradius;
			BorderColor = Color.White;
			BorderWidth = 10.0f;
		}

		public PEEllipse(Vector2 center, float xradius, float yradius, Color color)
		{
			Type = PEPrimitiveType.Circle;
			Position = center;
			XRadius = xradius;
			YRadius = yradius;
			BorderColor = color;
			BorderWidth = 10.0f;
		}

		public PEEllipse(Vector2 center, float xradius, float yradius, float layer, Color color)
		{
			Type = PEPrimitiveType.Circle;
			Position = center;
			XRadius = xradius;
			YRadius = yradius;
			Layer = layer;
			FillColor = color;
			IsFilled = true;
			BorderColor = Color.Black; ;
			BorderWidth = 1;
		}

		public override bool Intersection(PEPrimitive primitive)
		{
			throw new NotImplementedException();
		}

		public override bool Inside(Vector2 point)
		{
			throw new NotImplementedException();
		}

		public override void CreateUV()
		{
			throw new NotImplementedException();
		}

		public override void Draw(ref VertexPositionColorTexture[] vertices, ref int vertexIndex, ref short[] indices, ref int indiceIndex)
		{
			Matrix mat = Matrix.CreateScale(XRadius * 2f - BorderWidth * 2, YRadius * 2f - BorderWidth * 2, 1f) * Matrix.CreateRotationZ(Rotation) * Matrix.CreateTranslation(new Vector3(Position, -Layer));

			Vector3.Transform(circleIdentityCoords, ref mat, tempArray2);

			primitiveCount = 0;

			if (IsFilled)
			{
				// create a center vertex
				vertices[vertexIndex].Position = new Vector3(Position, -Layer);
				vertices[vertexIndex].Color = FillColor;
				vertices[vertexIndex].TextureCoordinate = Vector2.Zero;
				short centerIndex = (short)vertexIndex;
				vertexIndex++;

				for (int i = 1; i < slices; i++)
				{
					vertices[vertexIndex].Position = tempArray2[i - 1];
					vertices[vertexIndex].Color = FillColor;
					vertices[vertexIndex].TextureCoordinate = Vector2.Zero;
					vertexIndex++;

					vertices[vertexIndex].Position = tempArray2[i];
					vertices[vertexIndex].Color = FillColor;
					vertices[vertexIndex].TextureCoordinate = Vector2.Zero;
					vertexIndex++;

					indices[indiceIndex++] = centerIndex;
					indices[indiceIndex++] = (short)(vertexIndex - 2);
					indices[indiceIndex++] = (short)(vertexIndex - 1);

					primitiveCount++;
				}

				indices[indiceIndex++] = centerIndex;
				indices[indiceIndex++] = (short)(vertexIndex - 1);
				indices[indiceIndex++] = (short)(centerIndex + 1);

				primitiveCount++;
			}

			if (BorderWidth > 0)
			{
				mat = Matrix.CreateScale(XRadius * 2f, YRadius * 2f, 1f) * Matrix.CreateRotationZ(Rotation) * Matrix.CreateTranslation(new Vector3(Position, -Layer));

				Vector3.Transform(circleIdentityCoords, ref mat, tempArray1);

				for (int i = 0; i < slices; i++)
				{
					int index = vertexIndex;

					// 0
					vertices[vertexIndex].Position = tempArray1[i];
					vertices[vertexIndex].Color = BorderColor;
					vertices[vertexIndex].TextureCoordinate = Vector2.Zero;
					vertexIndex++;

					// 1
					vertices[vertexIndex].Position = tempArray2[i];
					vertices[vertexIndex].Color = BorderColor;
					vertices[vertexIndex].TextureCoordinate = Vector2.Zero;
					vertexIndex++;

					// 2
					if (i == slices - 1)
					{
						vertices[vertexIndex].Position = tempArray1[0];
						vertices[vertexIndex].Color = BorderColor;
						vertices[vertexIndex].TextureCoordinate = Vector2.Zero;
						vertexIndex++;

						// 3
						vertices[vertexIndex].Position = tempArray2[0];
						vertices[vertexIndex].Color = BorderColor;
						vertices[vertexIndex].TextureCoordinate = Vector2.Zero;
						vertexIndex++;
					}
					else
					{
						vertices[vertexIndex].Position = tempArray1[i + 1];
						vertices[vertexIndex].Color = BorderColor;
						vertices[vertexIndex].TextureCoordinate = Vector2.Zero;
						vertexIndex++;

						// 3
						vertices[vertexIndex].Position = tempArray2[i + 1];
						vertices[vertexIndex].Color = BorderColor;
						vertices[vertexIndex].TextureCoordinate = Vector2.Zero;
						vertexIndex++;
					}

					indices[indiceIndex++] = (short)(index + 0);
					indices[indiceIndex++] = (short)(index + 2);
					indices[indiceIndex++] = (short)(index + 1);

					indices[indiceIndex++] = (short)(index + 2);
					indices[indiceIndex++] = (short)(index + 3);
					indices[indiceIndex++] = (short)(index + 1);

					primitiveCount += 2;
				}
			}
		}
	}
}